#include <stdio.h>

const int max_len=1000;
const int move_len=4;

//检查边界
int checkEdge(int i,int j,int n){
    if(i<0||j<0||i>=n||j>=n)
    {
        return 0;
    }

    return 1;
}

void printArray(float **result_array,int n)
{
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<n;j++)
        {
            printf("%6.2f ",result_array[i][j]);
        }
        printf("\n");
    }
    printf("\n");

}

int formatInt(float f){
    int tmp=(int)f;
    int end=(f-tmp)>=0.5f?1:0;
    return tmp+end;
}

int main(){
    //存放输入数据
    int **array;
    //存放时间结果
    float **result_array;
    //搜索队列
    int **queue;
    int start,end;

    //不同地形花费时间
    float time[8]={-1,0,0,0,0,-1,-1,-1};
    //移动方式
    int move[move_len][2]={{0,1},{1,0},{0,-1},{-1,0}};
    int i,j,k;
    int n;

    
    while (scanf("%d",&n)!=EOF)
    {
        if(n==0)
        {
            break;
        }
        scanf("%f %f %f %f",&time[1],&time[2],&time[3],&time[4]);

        array=new int*[n];
        result_array=new float*[n];
        queue=new int*[n*n];

        for(i=0;i<n;i++)
        {
			array[i]=new int[n];
			result_array[i]=new float[n];

            for(j=0;j<n;j++)
            {
                scanf("%d",&array[i][j]);
                result_array[i][j]=-1;
                queue[i*n+j]=new int[2];
            }
        }
        
        result_array[n-1][0]=0;
        
        for(i=n-1;i>=0;i--)
        {
            for(j=0;j<n;j++)
            {   
                
                if(time[array[i][j]]<0)
                {
                    continue;
                }

                float minValue=-1;
                //搜索周围的点计算该点的时间消耗
                for(k=0;k<move_len;k++)
                {
                    int x=i+move[k][0];
                    int y=j+move[k][1];

                    if(checkEdge(x,y,n)&&result_array[x][y]>=0)
                    {
                        if(minValue<0||minValue>result_array[x][y])
                        {
                            minValue=result_array[x][y];
                        }
                    }
                }

                if(minValue>=0)
                {
                    result_array[i][j]=time[array[i][j]]+minValue;
                    queue[0][0]=i;
                    queue[0][1]=j;
                    start=0;
                    end=1;

                    //搜索从该点出发周围有没有更少花费点
                    while (start<end)
                    {
                        int nowx=queue[start][0];
                        int nowy=queue[start][1];
                        for(k=0;k<move_len;k++)
                        {
                            int x=nowx+move[k][0];
                            int y=nowy+move[k][1];

                            //未进行遍历的点不做搜索
                            if(x<i||(x==i&&y>j))
                            {
                                continue;
                            }
                            

                            if(checkEdge(x,y,n))
                            {
                                float timeHf=time[array[x][y]];
                                if(timeHf>0)
                                {
                                    float sum=result_array[nowx][nowy]+timeHf;
                                    //搜索到了入队 继续搜索
                                    if(result_array[x][y]>=0)
                                    {
                                        
                                        if(sum<result_array[x][y])
                                        {
                                            result_array[x][y]=sum;
                                            queue[end][0]=x;
                                            queue[end][1]=y;
                                            end++;
                                        }
                                    }
                                    else{
                                        result_array[x][y]=sum;
                                        queue[end][0]=x;
                                        queue[end][1]=y;
                                        end++;
                                    }
                                }
                                
                            
                            }
                        }
                        start++;
                        //printArray(result_array,n);
                    }
                
                }
                

                
            }
            
        }

        float min=-1;
        i=0;
        j=n-2;
        if(checkEdge(i,j,n))
        {
            if(min<0||(min>result_array[i][j]&&result_array[i][j]>=0))
            {
                min=result_array[i][j];
            }
        }
        i=1;
        j=n-1;
        if(checkEdge(i,j,n))
        {
            if(min<0||(min>result_array[i][j]&&result_array[i][j]>=0))
            {
                min=result_array[i][j];
            }
        }

        if(min<0)
        {
            printf("Impossible!\n");
        }
        else{
            printf("%d\n",formatInt(min));
        }

        for(i=0;i<n;i++)
        {
			delete array[i];
			delete result_array[i];
            for(j=0;j<n;j++)
            {
                delete queue[i*n+j];
            }
        }
        delete array;
        delete result_array;
        delete queue;
    }
    
    return 0;
}